package com.benew.ntt.ydeval

import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Build
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.util.SparseArray
import android.util.SparseIntArray
import androidx.annotation.RequiresApi
import com.benew.ntt.evaluate.EvalScore
import com.benew.ntt.evaluate.constant.EvalType
import com.ntt.core.nlogger.NLogger
import org.json.JSONArray
import org.json.JSONObject
import java.lang.StringBuilder
import java.util.regex.Pattern

object YDResultParse {
    val TAG = javaClass.simpleName

    //英语评测保留
    val SYMBOL = arrayOf(
        'A', 'a',
        'B', 'b',
        'C', 'c',
        'D', 'd',
        'E', 'e',
        'F', 'f',
        'G', 'g',
        'H', 'h',
        'I', 'i',
        'J', 'j',
        'K', 'k',
        'L', 'l',
        'M', 'm',
        'N', 'n',
        'O', 'o',
        'P', 'p',
        'Q', 'q',
        'R', 'r',
        'S', 's',
        'T', 't',
        'U', 'u',
        'V', 'v',
        'W', 'w',
        'X', 'x',
        'Y', 'y',
        'Z', 'z',
        '\'', ' ',
        'ˈ', 'ː',
        'ˌ',
        '0', '1',
        '2', '3',
        '4', '5',
        '6', '7',
        '8', '9',
        'æ', 'ɪ',
        'ɜ', 'ɑ',
        'ə', 'ɔ',
        'ʊ', 'ʃ',
        'ʒ', 'ð',
        'ŋ', 'ʌ',
        'θ', 'ɒ',
        '/'
    )

    @SuppressLint("UseSparseArrays")
    //评测返回word的index对应的该单词在原文本的起始位置
    val mIndexMap = SparseIntArray()

    /**
     * 设置评测内容每个字词的下标[mIndexMap]
     */
    @ExperimentalStdlibApi
    fun setupIndex(text: String?, type: String?, indexMap: SparseIntArray) {
        indexMap.clear()
        if (text == null) {
            return
        }
        NLogger.d(
            TAG,
            "评测的文本",
            text
        )
        //[PS]空格是⾳标标记，不参与打分，匹配index的时候去掉[PS]空格
        val textA = text.replace("[PS] ", "")

        NLogger.d(
            TAG,
            "[PS]空格是⾳标标记，不参与打分，匹配index的时候去掉[PS]空格",
            textA
        )
        val textB = StringBuilder()
        if (EvalType.ZH_CHS == type ||
            EvalType.CN_PRED == type ||
            EvalType.PHONETICIZE == type ) {
            //过滤字符串，属于汉字的保留，不属于的其他符号都替换成空格
            val regex = Regex("[\u4e00-\u9fa5]")//汉字正则
            textA.toCharArray().mapIndexed { index, c ->
                if (regex.matchesAt(textA, index)) {
                    textB.append(c)
                } else {
                    textB.append(' ')
                }
            }
            NLogger.d(
                TAG,
                "过滤字符串，属于汉字的保留，不属于的其他符号都替换成空格",
                textB
            )
            // 多个空格相邻合并成⼀个空格，
            val textC = textB.toString().replace(Regex(" +"), "");
            NLogger.d(
                TAG,
                "去掉空格",
                textC
            )
            var preI = 0
            textC.mapIndexed { index, s ->
                val i = text.indexOf(s, preI)
                if (i >= 0) {
                    indexMap.put(index, i)
                    preI = i + 1
                }
            }
        } else {
            //过滤字符串，属于symbol⾥⾯的保留，不属于的其他符号都替换成空格
            textA.toCharArray().map { c ->
                if (SYMBOL.contains(c)) {
                    textB.append(c)
                } else {
                    textB.append(' ')
                }
            }

            NLogger.d(
                TAG,
                "过滤字符串，属于symbol⾥⾯的保留，不属于的其他符号都替换成空格",
                textB
            )
            // 多个空格相邻合并成⼀个空格，
            var textC = textB.toString().replace(Regex(" +"), " ");
            NLogger.d(
                TAG,
                "多个空格相邻合并成⼀个空格",
                textC
            )
            textC = textC.trim()
            val split = textC.split(' ')
            //然后按空格切分string，切分出来的列表index从0开始
            NLogger.d(
                TAG,
                "然后按空格切分string，切分出来的列表index从0开始",
            )

            var preI = 0
            split.mapIndexed { index, s ->
                val i = text.indexOf(s, preI)
                if (i >= 0) {
                    indexMap.put(index, i)
                    preI = i + s.length
                }
            }
        }

        NLogger.d(
            TAG,
            "结果",
            indexMap
        )
    }

    /**
     * 解析结果，给字符串的每个字加上颜色
     * 【分数，有颜色的SpannableStringBuilder】
     */
    @OptIn(ExperimentalStdlibApi::class)
    fun parseResult(message: String?, type: String): Array<Any> {
        var overall = 0.0
        val text = SpannableStringBuilder()
        if (!message.isNullOrBlank()) {
            try {
                val messageObj = JSONObject(message)
                val result = messageObj.optJSONObject("result")

                //总分数
                overall = result?.optDouble("overall") ?: 0.0

                //评测文本
                val refText = result?.optString("refText")
                refText?.let { it ->
                    val indexMap = SparseIntArray()
                    setupIndex(refText, type, indexMap)
                    text.append(it)
                    val wordsArray = result.optJSONArray("words")
                    var prePosition = 0
                    wordsArray?.let { words ->
                        val length = words.length()
                        for (i in 0 until length) {
                            val wordObj = words.getJSONObject(i)
                            val score = wordObj.optInt("pronunciation")
                            val word = wordObj.optString("word")
                            val position = wordObj.optInt("index")
                            if (word.isNullOrBlank()) {
                                continue
                            }
                            var index: Int? = indexMap[position]

                            //如果indexMap中有该单词，index开始查找，
                            // 没有则从结果中的position位置开始查找
                            index = if (index == null || index < 0) {
                                text.indexOf(word, position)
                            } else {
                                text.indexOf(word, index)
                            }

                            //如果上面都没找到，那就从prePosition位置查找
                            if (index < 0) {
                                index = text.indexOf(word, prePosition)
                                if (index >= 0) {
                                    prePosition = index
                                }
                            }

                            //如果最后上面都没找到，那就从0位置查找吧
                            if (index < 0) {
                                index = text.indexOf(word)
                            }
                            if (index >= 0) {
                                NLogger.d(
                                    TAG,
                                    "index=$index；position=$position；word.length=${word.length}"
                                )
                                when {
                                    score >= EvalScore.STAR_FOUR -> {
                                        setSan(
                                            text,
                                            index,
                                            index + word.length,
                                            Color.parseColor("#74D95F")
                                        )
                                    }
                                    score >= EvalScore.STAR_ONE -> {
                                        setSan(
                                            text,
                                            index,
                                            index + word.length,
                                            Color.parseColor("#FFB604")
                                        )
                                    }
                                    else -> {
                                        setSan(
                                            text,
                                            index,
                                            index + word.length,
                                            Color.parseColor("#FF7040")
                                        )
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                NLogger.e(TAG, "parseResult 结果解析错误： ==> ${e.message}")
            }
        }

        return arrayOf(overall, text)
    }

    /**
     * 解析结果，给字符串的每个字加上颜色
     * {"refText":"”this is my cup","overall":42.899529,"scores":[{"start":1,"end":5,"score":80},{"start":6,"end":8,"score":79},{"start":9,"end":11,"score":17},{"start":12,"end":18,"score":7}]}
     */
    @OptIn(ExperimentalStdlibApi::class)
    fun parseResultSDK(message: String?, type: String): String {
        val jsonObject = JSONObject()
        val list = JSONArray()
        if (!message.isNullOrBlank()) {
            try {
                val messageObj = JSONObject(message)
                val result = messageObj.optJSONObject("result")

                //评测文本
                val refText = result?.optString("refText")
                jsonObject.put("refText", refText ?: "")
                jsonObject.put("overall", result?.optDouble("overall") ?: 0.0)
                refText?.let { it ->
                    val indexMap = SparseIntArray()
                    setupIndex(refText, type, indexMap)
                    val wordsArray = result.optJSONArray("words")
                    var prePosition = 0
                    wordsArray?.let { words ->
                        val length = words.length()
                        for (i in 0 until length) {
                            val wordObj = words.getJSONObject(i)
                            val score = wordObj.optInt("pronunciation")
                            val word = wordObj.optString("word")
                            val position = wordObj.optInt("index")
                            if (word.isNullOrBlank()) {
                                continue
                            }
                            var index: Int? = indexMap[position]

                            //如果indexMap中有该单词，index开始查找，
                            // 没有则从结果中的position位置开始查找
                            index = if (index == null || index < 0) {
                                it.indexOf(word, position)
                            } else {
                                it.indexOf(word, index)
                            }

                            //如果上面都没找到，那就从prePosition位置查找
                            if (index < 0) {
                                index = it.indexOf(word, prePosition)
                                if (index >= 0) {
                                    prePosition = index
                                }
                            }

                            //如果最后上面都没找到，那就从0位置查找吧
                            if (index < 0) {
                                index = it.indexOf(word)
                            }

                            if (index >= 0) {
                                val scoreJson = JSONObject()
                                scoreJson.put("start", index)
                                val end =
                                    if (index + word.length > it.length) it.length else index + word.length
                                scoreJson.put("end", end)
                                scoreJson.put("score", score)
                                NLogger.d(
                                    TAG,
                                    "index=$index；position=$position；word.length=${word.length}"
                                )
                                list.put(scoreJson)
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                NLogger.e(TAG, "parseResult 结果解析错误： ==> ${e.message}")
            }
        }
        jsonObject.put("scores", list)
        return jsonObject.toString()
    }


    /**
     * 设置样式
     */
    private fun setSan(text: SpannableStringBuilder, start: Int, end: Int, color: Int) {
        text.setSpan(
            ForegroundColorSpan(
                color
            ),
            start,
            end,
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
    }

    /**
     * 解析进度，每读一个字，根据分数给该字上颜色
     * 给原文本的字上色
     */
    fun parseProgress(
        message: String?,
        text: SpannableStringBuilder?,
    ) {
        if (!message.isNullOrBlank() && !text.isNullOrBlank()) {
            try {
                val messageObj = JSONObject(message)
                val result = messageObj.optJSONObject("result")
                val wordsArray = result?.optJSONArray("words")
                wordsArray?.let { words ->
                    val length = words.length()
                    for (i in 0 until length) {
                        val wordObj = words.getJSONObject(i)
                        val score = wordObj.optInt("pronunciation")
                        val word = wordObj.optString("word")
                        val position = wordObj.optInt("index")
                        if (word.isNullOrBlank()) {
                            continue
                        }

                        var start: Int? = mIndexMap[position]
                        if (start == null || start < 0) {
                            start = text.indexOf(word, position)
                        }
                        NLogger.d(
                            TAG,
                            "start=$start",
                        )
                        if (start >= 0) {
                            NLogger.d(
                                TAG,
                                "index=$start；word.length=${word.length}"
                            )
                            when {
                                score >= EvalScore.STAR_FOUR -> {
                                    setSan(
                                        text,
                                        start,
                                        start + word.length,
                                        Color.parseColor("#74D95F")
                                    )
                                }
                                score >= EvalScore.STAR_ONE -> {
                                    setSan(
                                        text,
                                        start,
                                        start + word.length,
                                        Color.parseColor("#FFB604")
                                    )
                                }
                                else -> {
                                    setSan(
                                        text,
                                        start,
                                        start + word.length,
                                        Color.parseColor("#FF7040")
                                    )
                                }
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                NLogger.e(TAG, "parseProgress 进度解析错误： ==> ${e.message}")
            }
        }
    }


    /**
     * 解析背诵进度，每读一个字，根据分数给该字上颜色，
     * 背诵：把读的字添加到文本末尾
     */
    fun parseReciteProgress(
        message: String?,
        text: SpannableStringBuilder?,
    ) {
        if (!message.isNullOrBlank() && text != null) {
            try {
                val messageObj = JSONObject(message)
                val result = messageObj.optJSONObject("result")
                val wordsArray = result?.optJSONArray("words")
                wordsArray?.let { words ->
                    val length = words.length()
                    for (i in 0 until length) {
                        val wordObj = words.getJSONObject(i)
                        val score = wordObj.optInt("pronunciation")
                        val word = wordObj.optString("word")
                        if (word.isNullOrBlank()) {
                            continue
                        }
                        val wordSpan = SpannableStringBuilder(word)
                        when {
                            score >= EvalScore.STAR_FOUR -> {
                                setSan(
                                    wordSpan,
                                    0,
                                    wordSpan.length,
                                    Color.parseColor("#74D95F")
                                )
                            }
                            score >= EvalScore.STAR_ONE -> {
                                setSan(
                                    wordSpan,
                                    0,
                                    wordSpan.length,
                                    Color.parseColor("#FFB604")
                                )
                            }
                            else -> {
                                setSan(
                                    wordSpan,
                                    0,
                                    wordSpan.length,
                                    Color.parseColor("#FF7040")
                                )
                            }
                        }
                        text.append(wordSpan)
                    }
                }
            } catch (e: Exception) {
                NLogger.e(TAG, "parseProgress 进度解析错误： ==> ${e.message}")
            }
        }
    }

    /**
     * 设置不及格的样式
     */
    fun getLowSpan(text: String?): SpannableStringBuilder {
        val span = SpannableStringBuilder()
        if (!text.isNullOrBlank()) {
            span.append(text)
            setSan(
                span,
                0,
                span.length,
                Color.parseColor("#FF7040")
            )
        }
        return span
    }
}